package org.streets.workflow.engine.entities;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import org.streets.workflow.engine.IProcessDefinition;
import org.streets.workflow.model.WFProcess;
import org.streets.workflow.model.io.BPDLParserException;
import org.streets.workflow.model.io.BPDLSerializerException;
import org.streets.workflow.model.io.JAXPBPDLParser;
import org.streets.workflow.model.io.JAXPBPDLSerializer;

/**
 * 流程定义相关信息对象
 *
 */
@Entity
@Table(name="WF_DT_DEFINITION")
public class ProcessDefinition implements IProcessDefinition {
	@Id
    protected String id; //主键
	@Column
    protected String name;//流程显示名称
	@Column
    protected String description;//流程业务说明
	@Column
    protected Boolean published;//是否发布，1=已经发布,0未发布
	@Column
    protected String uploadUser; //上载到数据库的操作员
	@Column
    protected Date uploadTime; //上载到数据库的时间
	@Column
    protected String publishUser; //发布人
	@Column
    protected Date publishTime; //发布时间
    @Column
    protected String definitionId; //流程定义名称-标识
    @Column
    protected Integer definitionVersion; //版本号
	@Column
    protected String definitionContent; //流程定义文件的内容

	protected transient WFProcess processModel;
	
    /* (non-Javadoc)
     * @see org.streets.workflow.engine.entities.IProcessDefinition#getId()
     */
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    /* (non-Javadoc)
     * @see org.streets.workflow.engine.entities.IProcessDefinition#getDefinitionId()
     */
    public String getDefinitionId() {
        return definitionId;
    }

    public void setDefinitionId(String processId) {
        this.definitionId = processId;
    }

    public Integer getDefinitionVersion() {
        return definitionVersion;
    }

    public void setDefinitionVersion(Integer version) {
        this.definitionVersion = version;
    }

    public String getDefinitionContent() {
        return definitionContent;
    }

    public void setDefinitionContent(String definitionContent) {
        this.definitionContent = definitionContent;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getPublishTime() {
        return publishTime;
    }

    public void setPublishTime(Date publishTime) {
        this.publishTime = publishTime;
    }

    public String getPublishUser() {
        return publishUser;
    }

    public void setPublishUser(String publisher) {
        this.publishUser = publisher;
    }

    public Boolean isPublished() {
        return published;
    }

    public void setPublished(Boolean published) {
        this.published = published;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

	public String getUploadUser() {
		return uploadUser;
	}

	public void setUploadUser(String uploadUser) {
		this.uploadUser = uploadUser;
	}

	public Date getUploadTime() {
		return uploadTime;
	}

	public void setUploadTime(Date uploadTime) {
		this.uploadTime = uploadTime;
	}
	
    public WFProcess getModel() {
    	
        if (processModel == null) {
        	
            if (this.definitionContent != null && !this.definitionContent.trim().equals("")) {

                ByteArrayInputStream in = null;
                try {
                	JAXPBPDLParser parser = new JAXPBPDLParser();
                    in = new ByteArrayInputStream(this.definitionContent.getBytes("utf-8"));
                    this.processModel = parser.parse(in);

                } catch (UnsupportedEncodingException ex) {
                    Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException(ex.getMessage());
                } catch (IOException ex) {
                    Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException(ex.getMessage());
                } catch(BPDLParserException ex){
                    Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
                    throw new RuntimeException(ex.getMessage());
                } finally {
                    try {
                        in.close();
                    } catch (IOException ex) {
                        Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
        return processModel;
    }

    /**
     * @param process
     * @throws RuntimeException
     */
    public void setProcessModel(WFProcess process) {
        try {
            this.processModel = process;
            this.definitionId = processModel.getName();
            this.name = processModel.getDisplayName(); 
            this.description = processModel.getDescription();

            JAXPBPDLSerializer ser = new JAXPBPDLSerializer();
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            ser.serialize(processModel, out);
            this.definitionContent = out.toString("utf-8");
            
        } catch (BPDLSerializerException ex) {
            Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex.toString());
        } catch (IOException ex) {
            Logger.getLogger(ProcessDefinition.class.getName()).log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex.toString());
        }
    }	
}
